% Licensed under the Apache License, Version 2.0 (the "License"); you may not
% use this file except in compliance with the License. You may obtain a copy of
% the License at
%
%   http://www.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
% License for the specific language governing permissions and limitations under
% the License.

%%% @author CA Meijer
%%% @copyright 2012 CA Meijer
%%% @doc This module provides functions to get, list, add, delete and discover
%%%      Nimbula objects.
%%% @end

-module(nimbula_objects).

%% Include files

%% Exported functions
-export([add/3,
		 add/4,
		 delete/3,
		 discover/2,
		 discover/3,
		 get/3,
		 get/4,
		 list/2,
		 list/3,
		 update/4]).


%% API
add(Pid, {ObjectType, ObjectFields}, Object) ->
	ObjectTypeStr = atom_to_list(ObjectType),
	add(Pid, {ObjectType, ObjectFields}, ObjectTypeStr, Object).

add(Pid, {ObjectType, ObjectFields}, ObjectPath, Object) ->
	Body = nimbula_json:record_to_json({ObjectType, ObjectFields}, Object),
	case nimbula:post(Pid, ObjectPath ++ "/", Body) of
		{ok, Json} ->
			nimbula_json:json_to_record({ObjectType, ObjectFields}, Json);
		Error ->
			Error
	end.

delete(Pid, {ObjectType, _ObjectFields}, Object) ->
	ObjectTypeStr = atom_to_list(ObjectType),
	ObjectStr = nimbula_utils:remove_slashes(nimbula_utils:to_string(Object)),
	case nimbula:delete(Pid, ObjectTypeStr ++ "/" ++ ObjectStr) of
		{ok, <<>>} ->
			ok;
		Error ->
			Error
	end.

get(Pid, {ObjectType, ObjectFields}, Object) ->
	ObjectTypeStr = atom_to_list(ObjectType),
	ObjectStr = nimbula_utils:remove_slashes(nimbula_utils:to_string(Object)),
	case nimbula:get(Pid, ObjectTypeStr ++ "/" ++ ObjectStr, 
					 nimbula_config:get_accept_type()) of
		{ok, Json} ->
			nimbula_json:json_to_record({ObjectType, ObjectFields}, Json);
		Error ->
			Error
	end.

get(Pid, {ObjectType, _ObjectFields}, Object, AcceptType) ->
	ObjectTypeStr = atom_to_list(ObjectType),
	ObjectStr = nimbula_utils:remove_slashes(nimbula_utils:to_string(Object)),
	nimbula:get(Pid, ObjectTypeStr ++ "/" ++ ObjectStr, AcceptType).

discover(Pid, {ObjectType, _ObjectFields}) ->
	ObjectTypeStr = atom_to_list(ObjectType),
	case nimbula:get(Pid, ObjectTypeStr ++ "/", 
					 nimbula_config:get_discovery_accept_type()) of
		{ok, Json} ->
			{struct, [{<<"result">>, Result}]} =	mochijson2:decode(Json),
			Result;
		Error ->
			Error
	end.

discover(Pid, {ObjectType, ObjectFields}, "") ->
	discover(Pid, {ObjectType, ObjectFields});
discover(Pid, {ObjectType, ObjectFields}, "/") ->
	discover(Pid, {ObjectType, ObjectFields});
discover(Pid, {ObjectType, ObjectFields}, <<>>) ->
	discover(Pid, {ObjectType, ObjectFields});
discover(Pid, {ObjectType, ObjectFields}, <<"/">>) ->
	discover(Pid, {ObjectType, ObjectFields});
discover(Pid, {ObjectType, _ObjectFields}, Container) ->
	ObjectTypeStr = atom_to_list(ObjectType),
	ContainerStr = nimbula_utils:remove_slashes(nimbula_utils:to_string(Container)),
	case nimbula:get(Pid, ObjectTypeStr ++ "/" ++ ContainerStr ++ "/", 
					 nimbula_config:get_discovery_accept_type()) of
		{ok, Json} ->
			{struct, [{<<"result">>, Result}]} =	mochijson2:decode(Json),
			Result;
		Error ->
			Error
	end.

list(Pid, {ObjectType, ObjectFields}) ->
	ObjectTypeStr = atom_to_list(ObjectType),
	case nimbula:get(Pid, ObjectTypeStr ++ "/", nimbula_config:get_accept_type()) of
		{ok, Json} ->
			nimbula_json:json_to_record_list({ObjectType, ObjectFields}, Json);
		Error ->
			Error
	end.

list(Pid, {ObjectType, ObjectFields}, "") ->
	list(Pid, {ObjectType, ObjectFields});
list(Pid, {ObjectType, ObjectFields}, "/") ->
	list(Pid, {ObjectType, ObjectFields});
list(Pid, {ObjectType, ObjectFields}, <<>>) ->
	list(Pid, {ObjectType, ObjectFields});
list(Pid, {ObjectType, ObjectFields}, <<"/">>) ->
	list(Pid, {ObjectType, ObjectFields});
list(Pid, {ObjectType, ObjectFields}, Object) ->
	ObjectTypeStr = atom_to_list(ObjectType),
	ObjectStr = nimbula_utils:remove_slashes(nimbula_utils:to_string(Object)),
	case nimbula:get(Pid, ObjectTypeStr ++ "/" ++ ObjectStr ++ "/", 
					 nimbula_config:get_accept_type()) of
		{ok, Json} ->
			nimbula_json:json_to_record_list({ObjectType, ObjectFields}, Json);
		Error ->
			Error
	end.

update(Pid, {ObjectType, ObjectFields}, ObjectPath, Object) ->
	ObjectTypeStr = atom_to_list(ObjectType),
	ObjectPathStr = nimbula_utils:remove_slashes(nimbula_utils:to_string(ObjectPath)),
	Body = nimbula_json:record_to_json({ObjectType, ObjectFields}, Object),
	case nimbula:put(Pid, ObjectTypeStr ++ "/" ++ ObjectPathStr, Body) of
		{ok, Json} ->
			nimbula_json:json_to_record({ObjectType, ObjectFields}, Json);
		Error ->
			Error
	end.
